import type { MapItemGroup } from './types'

export interface MapItemIndex<T> {
  before?: string[]
  enable(): boolean
  search(
    lng: number,
    lat: number,
    radius: number,
    results: Record<string, MapItemGroup<any>>
  ): T[] | Set<T> | null | undefined
}

const indexes: { type: string; index: MapItemIndex<any> }[] = []

export function registerIndex(type: string, index: MapItemIndex<any>) {
  if (!index.before || indexes.length === 0) {
    indexes.push({ type, index })
    return
  }
  let idx = indexes.length
  for (const b of index.before) {
    const idx1 = indexes.findIndex((idx) => idx.type === b)
    if (idx1 > 0 && idx1 < idx) {
      idx = idx1
    }
  }
  indexes.splice(idx, 0, { type, index })
}

export function searchMapItems(
  lng: number,
  lat: number,
  radius: number
): Record<string, MapItemGroup<any>> | null {
  const ret: Record<string, MapItemGroup<any>> = {}
  let empty = true
  for (const { type, index } of indexes) {
    if (!index.enable()) {
      continue
    }
    const data = index.search(lng, lat, radius, ret)
    if (!data) {
      continue
    }
    if (data instanceof Set) {
      if (data.size === 0) {
        continue
      }
      ret[type] = { type, items: [...data] }
      empty = false
    } else {
      if (data.length === 0) {
        continue
      }
      ret[type] = { type, items: data }
      empty = false
    }
  }
  if (empty) {
    return null
  }
  return ret
}
